package tool.zyk.protocol;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import lombok.extern.slf4j.Slf4j;
import tool.zyk.configuration.SimpleRpcConfiguration;
import tool.zyk.consts.RpcCommonConst;
import tool.zyk.invoke.ReflectExecutor;
import tool.zyk.serializable.SerializableConverter;
import tool.zyk.serializable.SerializableFactory;
import tool.zyk.stardand.RpcRequest;
import tool.zyk.stardand.RpcResponse;
import tool.zyk.utils.LogUtil;
import tool.zyk.utils.ReflectUtils;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @author feite.zyk
 * @time 2024/2/1 10:37
 * @description
 */
@Slf4j
public class ProtocolRequestM2MDecoder extends MessageToMessageDecoder<RpcRequest> {
    private final SimpleRpcConfiguration simpleRpcConfiguration;

    public ProtocolRequestM2MDecoder(SimpleRpcConfiguration configuration) {
        super();
        this.simpleRpcConfiguration = configuration;
    }

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, RpcRequest rpcRequest, List<Object> list) throws Exception {

        log.debug("rpcRequest:{}", rpcRequest);
        try {
            String beUseClass = rpcRequest.getBeUseClass();
            String methodCode = rpcRequest.getMethodCode();
            Object[] args = rpcRequest.getArgs();
            Method method = ReflectUtils.getMethod(beUseClass, methodCode);

            ReflectExecutor executor = simpleRpcConfiguration.getExecutorFactory().getExecutor();
            Object result = executor.doInvoke(method, args);
            log.info("执行结果:{}", result);
            SerializableConverter serializableConverter = SerializableFactory.getSerializableConverter(simpleRpcConfiguration.getSerializableType());
            channelHandlerContext.channel().writeAndFlush(RpcResponse.ofSuccess(serializableConverter.parseTransferData2Object(result), result.getClass().getName()));
        } catch (Exception exception) {
            LogUtil.printErrorLog(exception);
            channelHandlerContext.channel().writeAndFlush(RpcResponse.ofFailed(exception.getMessage(), RpcCommonConst.StatusCode.FAILED_CODE));

        }


    }

}
